<?php
/** @noinspection PhpUnused */
declare(strict_types=1);

namespace app\shop\controller;

use app\shop\enums\order\OrderPayWay;
use app\shop\enums\payment\OrderType;
use app\shop\enums\payment\TradeState;
use app\shop\exception\FailException;
use app\shop\library\pay\PayProvider;
use app\shop\library\ShopLogHelper;
use app\shop\logic\OrderLogic;
use app\shop\logic\RechargeLogic;
use app\shop\model\order\OrderModel;
use app\shop\model\PaymentTradeModel;
use app\shop\model\recharge\RechargeOrderModel;
use GuzzleHttp\Psr7\Response;
use Psr\Http\Message\ResponseInterface;
use think\Request;
use Throwable;
use Yansongda\Pay\Pay;

class NotifyController extends BaseController
{
    protected array $noNeedLogin = ['*'];

    /**
     * 微信支付回调通知
     * @param Request $request
     * @return Response|ResponseInterface
     */
    public function wxpay(Request $request): Response|ResponseInterface
    {
        ShopLogHelper::info(PHP_EOL . '触发微信支付回调通知');
        try {
            $payProvider = new PayProvider(OrderPayWay::WXPAY);
            $wxpayObject = $payProvider->getProvider()->getPayObject();
            try {
                $callbackData = $wxpayObject->callback()->toArray();
            } catch (Throwable) {
                $callbackData = $wxpayObject->callback($request->request())->toArray();
            }
            ShopLogHelper::info('接收到微信支付回调数据', $callbackData);
            $data = $callbackData['resource']['ciphertext'];
            // 验证回调数据
            $paymentTrade = PaymentTradeModel::where('out_trade_no', $data['out_trade_no'])->findOrEmpty();
            if ($paymentTrade->isEmpty()) {
                ShopLogHelper::error('第三方支付记录不存在');
                return $wxpayObject->success();
            }

            switch ($paymentTrade->trade_state) {
                case OrderType::SHOP:
                    $orderModel = new OrderModel();
                    break;
                case OrderType::RECHARGE:
                    $orderModel = new RechargeOrderModel();
                    break;
                default:
                    ShopLogHelper::error('订单类型异常');
                    return $wxpayObject->success();
            }
            $order = $orderModel::where('id', $paymentTrade->order_id)->findOrEmpty();
            if ($order->isEmpty()) {
                ShopLogHelper::error('支付订单不存在');
                return $wxpayObject->success();
            }
            $tradeResult = $payProvider->query([
                'out_trade_no' => $paymentTrade->out_trade_no,
                'source'       => $paymentTrade->source
            ]);
            ShopLogHelper::info("查询支付单号【 $order->out_trade_no 】支付结果", $tradeResult);

            if ($tradeResult['trade_state'] === 'REFUND') {
                ShopLogHelper::info('订单已退款');
                return $wxpayObject->success();
            }
            if ($tradeResult['trade_state'] !== 'SUCCESS') {
                ShopLogHelper::error('支付状态异常');
                return $wxpayObject->success();
            }
            $payPrice = intval($order->pay_price * 100);
            if ($tradeResult['amount']['payer_total'] !== $payPrice) {
                ShopLogHelper::error('支付金额异常');
                return $wxpayObject->success();
            }

            //更新第三方支付信息
            $paymentTrade->trade_no    = $data['transaction_id'];
            $paymentTrade->trade_state = TradeState::PAID;
            $paymentTrade->pay_result  = $tradeResult;
            $paymentTrade->save();

            // 处理订单数据
            switch (intval($paymentTrade->order_type)) {
                case OrderType::SHOP:
                    $logic = new OrderLogic();
                    $logic->processShopOrder($paymentTrade->order_id);
                    break;
                case OrderType::RECHARGE:
                    $logic = new RechargeLogic();
                    $logic->processRechargeOrder($paymentTrade->order_id);
                    break;
            }

            ShopLogHelper::info('微信支付回调处理完成');
        } catch (Throwable $e) {
            ShopLogHelper::info('微信回调异常', ['error' => $e->getMessage()]);
            return new Response(
                500,
                ['Content-Type' => 'application/json'],
                json_encode(['code' => 'FAIL', 'message' => '失败']),
            );
        }

        return $wxpayObject->success();
    }

    /**
     * 微信退款回调通知
     * @param Request $request
     * @return Response|ResponseInterface
     */
    public function wxpayRefund(Request $request): Response|ResponseInterface
    {
        ShopLogHelper::info(PHP_EOL . '触发微信退款回调通知');
        try {
            $payProvider = new PayProvider(OrderPayWay::WXPAY);
            $wxpayObject = $payProvider->getProvider()->getPayObject();
            try {
                $callbackData = $wxpayObject->callback()->toArray();
            } catch (Throwable) {
                $callbackData = $wxpayObject->callback($request->request())->toArray();
            }
            ShopLogHelper::info('接收到微信退款回调数据', $callbackData);
            $cipherText = $callbackData['resource']['ciphertext'];
            // 验证回调数据
            $paymentTrade = PaymentTradeModel::where('out_trade_no', $cipherText['out_trade_no'])->findOrEmpty();
            if ($paymentTrade->isEmpty()) {
                throw new FailException('第三方支付订单不存在');
            }
            $refundResult = $payProvider->queryRefund([
                'out_trade_no' => $cipherText['out_refund_no'],
                'source'       => $paymentTrade->source
            ]);
            ShopLogHelper::info("查询支付订单【 $paymentTrade->out_trade_no 】退款结果", $refundResult);

            //更新第三方支付信息
            $paymentTrade->trade_state   = TradeState::REFUND;
            $paymentTrade->refund_result = $refundResult;
            $paymentTrade->save();

            ShopLogHelper::info('微信退款回调处理完成');
        } catch (Throwable $e) {
            ShopLogHelper::info('微信回调异常', ['error' => $e->getMessage()]);
            return new Response(
                500,
                ['Content-Type' => 'application/json'],
                json_encode(['code' => 'FAIL', 'message' => '失败']),
            );
        }

        return $wxpayObject->success();
    }

    /**
     * 支付宝支付回调通知
     * @param Request $request
     * @return Response|ResponseInterface
     */
    public function alipay(Request $request): Response|ResponseInterface
    {
        ShopLogHelper::info(PHP_EOL . '触发支付宝回调通知');
        try {
            $payProvider  = new PayProvider(OrderPayWay::ALIPAY);
            $alipayObject = $payProvider->getProvider()->getPayObject();
            try {
                $callbackData = $alipayObject->callback()->toArray();
            } catch (Throwable) {
                // 如果解析失败则尝试传递请求参数
                $callbackData = $alipayObject->callback($request->request())->toArray();
            }
            ShopLogHelper::info('接收到支付宝回调数据', $callbackData);
            // 验证回调数据
            $paymentTrade = PaymentTradeModel::where('out_trade_no', $callbackData['out_trade_no'])->findOrEmpty();
            if ($paymentTrade->isEmpty()) {
                ShopLogHelper::error('第三方支付记录不存在');
                return $alipayObject->success();
            }

            switch ($paymentTrade->order_type) {
                case OrderType::SHOP:
                    $orderModel = new OrderModel();
                    break;
                case OrderType::RECHARGE:
                    $orderModel = new RechargeOrderModel();
                    break;
                default:
                    ShopLogHelper::error('订单类型异常');
                    return $alipayObject->success();
            }

            $order = $orderModel::where('id', $paymentTrade->order_id)->findOrEmpty();
            if ($order->isEmpty()) {
                ShopLogHelper::error('支付订单不存在');
                return $alipayObject->success();
            }
            $tradeResult = $payProvider->query([
                'out_trade_no' => $callbackData['out_trade_no'],
                'source'       => $paymentTrade->source,
            ]);
            ShopLogHelper::info("查询支付单号【 $order->out_trade_no 】支付结果", $tradeResult);

            if ($tradeResult['trade_status'] === 'TRADE_CLOSED') {
                // 更新第三方支付信息
                $paymentTrade->refund_result = $tradeResult;
                $paymentTrade->trade_state   = TradeState::REFUND;
                $paymentTrade->save();

                ShopLogHelper::info('订单已关闭或退款');
                return Pay::alipay()->success();
            }
            if ($tradeResult['trade_status'] !== 'TRADE_SUCCESS') {
                ShopLogHelper::error('支付状态异常', $tradeResult);
                return $alipayObject->success();
            }
            if ($tradeResult['total_amount'] !== $order->pay_price) {
                ShopLogHelper::error('支付金额异常', $tradeResult);
                return $alipayObject->success();
            }

            //更新第三方支付信息
            $paymentTrade->trade_no    = $callbackData['trade_no'];
            $paymentTrade->trade_state = TradeState::PAID;
            $paymentTrade->pay_result  = $tradeResult;
            $paymentTrade->save();

            // 处理订单数据
            switch (intval($paymentTrade->order_type)) {
                case OrderType::SHOP:
                    $logic = new OrderLogic();
                    $logic->processShopOrder($paymentTrade->order_id);
                    break;
                case OrderType::RECHARGE:
                    $logic = new RechargeLogic();
                    $logic->processRechargeOrder($paymentTrade->order_id);
                    break;
            }

            ShopLogHelper::info('支付回调处理完成');
        } catch (Throwable $e) {
            ShopLogHelper::error('支付宝回调异常', ['error' => $e->getMessage()]);
            return new Response(
                500,
                ['Content-Type' => 'application/json'],
                json_encode(['code' => 'FAIL', 'message' => '失败']),
            );
        }

        return $alipayObject->success();
    }

    /**
     * 支付宝退款回调通知
     * @param Request $request
     * @return Response|ResponseInterface
     */
    public function alipayRefund(Request $request): Response|ResponseInterface
    {
        ShopLogHelper::info(PHP_EOL . '触发支付宝退款回调通知');
        try {
            $payProvider  = new PayProvider(OrderPayWay::ALIPAY);
            $alipayObject = $payProvider->getProvider()->getPayObject();
            try {
                $callbackData = $alipayObject->callback()->toArray();
            } catch (Throwable) {
                $callbackData = $alipayObject->callback($request->request())->toArray();
            }
            ShopLogHelper::info('接收到支付宝退款回调数据', $callbackData);
            // 验证回调数据
            $paymentTrade = PaymentTradeModel::where('out_trade_no', $callbackData['out_trade_no'])->findOrEmpty();
            if ($paymentTrade->isEmpty()) {
                ShopLogHelper::error('第三方支付记录不存在');
                return $alipayObject->success();
            }
            $refundResult = $payProvider->queryRefund([
                'out_trade_no' => $paymentTrade->out_trade_no,
                'source'       => $paymentTrade->source
            ]);
            ShopLogHelper::info("查询支付订单【 $paymentTrade->out_trade_no 】退款结果", $refundResult);
            if ($refundResult['trade_status'] === 'TRADE_CLOSED') {
                //更新第三方支付信息
                $paymentTrade->trade_state   = TradeState::REFUND;
                $paymentTrade->refund_result = $refundResult;
                $paymentTrade->save();

                ShopLogHelper::info('支付包退款回调处理完成');
            }
        } catch (Throwable $e) {
            ShopLogHelper::error('支付宝退款回调异常', ['error' => $e->getMessage()]);
            return new Response(
                500,
                ['Content-Type' => 'application/json'],
                json_encode(['code' => 'FAIL', 'message' => '失败']),
            );
        }

        return $alipayObject->success();
    }
}